package com.yuyou.fn.educational.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.rocketmq.Producer;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.mapper.ClassLectureMapper;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.ArrangeClassTimeResultVo;
import com.yuyou.fn.educational.vo.AttendClassRecordUpdateVo;
import com.yuyou.fn.educational.vo.AttendClassRecordVo;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 *
 * ClassLecture 表数据服务层接口实现类
 *
 */
@Service
public class ClassLectureServiceImpl extends SuperServiceImpl<ClassLectureMapper, ClassLecture,Long> implements IClassLectureService {


    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private IFinishLectureService finishLectureService ;

    @Resource
    private IAttendClassRecordService attendClassRecordService ;

    @Resource
    private ITeacherService teacherService;


    @Resource
    private Producer producer;

    @Resource
    private IStudentService studentService;

    @Resource
    private IArrangeTeacherHistoryService arrangeTeacherHistoryService;

    @Resource
    private IArrangeLectureHistoryService arrangeLectureHistoryService;

    @Value("${dev.env}")
    private boolean dev;


    @Override
    public void createClassLecture(Long classId, Integer lectureAmount) {
        List<ClassLecture> list  = new ArrayList<>(lectureAmount);
        for(int i = 1 ;i <= lectureAmount ;i++ ){
            ClassLecture classLecture = new ClassLecture() ;
            classLecture.setClassId(classId);
            classLecture.setLectureNo(i);

            classLecture.setUpdateTime(TimeUtils.now());
            classLecture.setCreateTime(TimeUtils.now());
            classLecture.setAbsenceAmount(0);
            classLecture.setAttendanceAmount(0);
            classLecture.setLateAmount(0);
            classLecture.setLeaveAmount(0);
            classLecture.setAttendanceStatus(0);
            classLecture.setTotalAmount(0);

            classLecture.setCreateTime(TimeUtils.now());
            classLecture.setUpdateTime(TimeUtils.now());
            list.add(classLecture);
        }
        insertBatch(list);
    }

    @Transactional
    @Override
    public void saveArrangeClassTimeResult(Long classId, List<ArrangeClassTimeResultVo> arrangeClassLectureResultList) {
        Collections.sort(arrangeClassLectureResultList, new Comparator<ArrangeClassTimeResultVo>() {
            @Override
            public int compare(ArrangeClassTimeResultVo o1, ArrangeClassTimeResultVo o2) {
                return o1.getLectureNo() - o2.getLectureNo();
            }
        });
        for(int i = 1 ;i <= arrangeClassLectureResultList.size() ;i++ ){
            ArrangeClassTimeResultVo arrangeClassLectureResultVo = arrangeClassLectureResultList.get(i - 1);

            Example<ClassLecture> example = ClassLecture.createExample();
            example.createCriteria().andEqualTo("classId" , classId).andEqualTo("lectureNo" , i );
            ClassLecture classLecture = new ClassLecture();
            classLecture.setClassDate(TimeUtils.parse(arrangeClassLectureResultVo.getDate(),"yyyy-MM-dd"));
            String[] times = arrangeClassLectureResultVo.getTime().split("-");
            classLecture.setStartTime(times[0]);
            classLecture.setEndTime(times[1]);
            classLecture.setClassTime(TimeUtils.parse(arrangeClassLectureResultVo.getDate() + times[0] , "yyyy-MM-ddHH:mm"));
            boolean s = updateSelectiveByExample(classLecture, example);
            if(!s){
                saveClassLecture(classId, i, classLecture);
            }
        }

    }

    public ClassLecture findClassLectureByClassIdLectureNo(Long classId, int lectureNo) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("classId" , classId).andEqualTo("lectureNo" , lectureNo );
        return findOneByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureByClassIdsLectureNo(List<Long> classIds, int lectureNo,int attendanceStatus) {

        if (Utils.checkListEmpty(classIds)){
            return Collections.EMPTY_LIST;
        }
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andIn("classId" , classIds).andEqualTo("lectureNo" , lectureNo ).andEqualTo("attendanceStatus",attendanceStatus);
        return findListByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureByClassId(Long classId) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.orderBy("lectureNo");
        example.createCriteria().andEqualTo("classId",classId);
        return findListByExample(example);
    }

    @Transactional
    @Override
    public void saveArrangementTeacher(Long classId, List<Long> teacherIds) {
        List<Teacher> teacherList = teacherService.findByIds(teacherIds);
        Map<Long , Teacher> teacherMap = BeanUtils.toMap(teacherList,"teacherId");
        List<ClassLecture> classLectureList = findClassLectureByClassId(classId);
        Map<Integer,ClassLecture> classLectureMap = BeanUtils.toMap(classLectureList,"lectureNo");
        for(int i = 1 ;i <= teacherIds.size() ;i++ ){
            ClassLecture classLecture = classLectureMap.get(i);
            ClassLecture update = new ClassLecture();
            update.setUpdateTime(TimeUtils.now());
            update.setClassLectureId(classLecture.getClassLectureId());
            Long teacherId = teacherIds.get(i - 1);
            update.setTeacherId(teacherId );
            update.setTeacherName(teacherMap.get(teacherId).getTeacherName());
            detectConflict(teacherId,classLecture.getClassDate(),classLecture.getStartTime(),classLecture.getEndTime() );
            updateSelectiveById(update);
        }
    }

    private void detectConflict(Long teacherId , Date classDate , String startTime , String endTime  ) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("teacherId",teacherId ).andEqualTo("classDate",classDate );
        List<ClassLecture> timeList = findListByExample(example);

        if(timeList!=null && timeList.size() != 0 ){
            for(ClassLecture t : timeList ){
                if( !(endTime.compareTo(t.getStartTime())<=0 || startTime.compareTo(t.getEndTime())>=0) ){
                    CourseClass courseClass=courseClassService.findById(t.getClassId(),"classId","className","classNo");
                    Teacher teacher=teacherService.findById(teacherId,"teacherId","teacherName");
                    throw new BusException("请核实，"+teacher.getTeacherName()+" 老师 已在这个时间段里排了 "+"("+courseClass.getClassNo()+")"+courseClass.getClassName()+"课程了哦！");
                }
            }
        }

    }

    private void saveClassLecture(Long classId, int lectureNo, ClassLecture classLecture) {
        classLecture.setClassId(classId);
        classLecture.setLectureNo(lectureNo);
        classLecture.setCreateTime(TimeUtils.now());
        classLecture.setUpdateTime(TimeUtils.now());
        insertSelective(classLecture);
    }

    @Override
    public List<ClassLecture> findClassLectureByTeacherId(Long teacherId, Date start, Date end) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("teacherId",teacherId).andBetween("classDate" ,start ,end );
        return findListByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureByClassIdAndDateString(Long classId, String  dateString) {
        Example<ClassLecture> example = ClassLecture.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("classId",classId);
        criteria.andLike("classDate",dateString+"%");
        example.orderBy("classDate");
        return findListByExample(example);
    }

    @Override
    public void createAttendanceRecordForStudent(List<StudentReg> studentRegList) {
        for(StudentReg studentReg : studentRegList ){
            createAttendanceRecordForStudent(studentReg);
        }
    }





    @Override
    public void createAttendanceRecordForStudent(StudentReg studentReg) {

        if(studentReg == null || studentReg.getRegStatus() == null || studentReg.getRegStatus() == 4 ){
            return ;
        }

        final List<ClassLecture> classLectureList = findClassLectureByClassId(studentReg.getClassId());

        List<AttendClassRecord> attendClassRecordList = new ArrayList<>(20);
        for(ClassLecture classLecture : classLectureList ){
            if(classLecture.getLectureNo() >= studentReg.getStartAmount() && classLecture.getLectureNo() <= studentReg.getEndAmount() ){
                AttendClassRecord classLectureDetail = new AttendClassRecord();
                classLectureDetail.setAttendanceStatus(0);
                Integer attendanceStatus = classLecture.getAttendanceStatus();
                classLectureDetail.setIsAttendance(attendanceStatus != null && attendanceStatus == 1 ? 1 : 0);
                classLectureDetail.setFinanceFlag(0);
                classLectureDetail.setCreateTime(TimeUtils.now());
                classLectureDetail.setClassLectureId(classLecture.getClassLectureId());
                classLectureDetail.setStudentId(studentReg.getStudentId());
                classLectureDetail.setUpdateTime(TimeUtils.now());
                classLectureDetail.setStudentName(studentReg.getStudentName());
                classLectureDetail.setClassId(studentReg.getClassId());
                classLectureDetail.setRegId(studentReg.getRegId());
                classLectureDetail.setShiftStatus(0);
                attendClassRecordList.add(classLectureDetail);
            }

        }

        try{
            attendClassRecordService.insertBatch(attendClassRecordList) ;
        }catch (Exception e){
            for(AttendClassRecord attendClassRecord : attendClassRecordList){
                try{
                    attendClassRecordService.insertSelective(attendClassRecord);
                }catch (Exception se){
                    //ignore
                }
            }
        }

        List<Long> classLectureIds = BeanUtils.toList(classLectureList,"classLectureId");
        updateTotalAmount(classLectureIds) ;


    }

    public void updateTotalAmount(List<Long> classLectureIds ) {
        for(Long  classLectureId : classLectureIds ){
            Integer amount  = attendClassRecordService.countByClassLectureId(classLectureId);
            ClassLecture update = new ClassLecture();
            update.setClassLectureId(classLectureId);
            update.setTotalAmount(amount);
            update.setUpdateTime(TimeUtils.now());
            updateSelectiveById(update);
        }
    }


    @Override
    public List<AttendClassRecord> findAttendClassRecordByClassLectureId(Long classLectureId) {
        Example<AttendClassRecord> example = AttendClassRecord.createExample();
        example.createCriteria().andEqualTo("classLectureId",classLectureId);
        example.orderBy("shiftStatus").desc().orderBy("attendanceStatus").desc();
        return attendClassRecordService.findListByExample(example);
    }

    @Override
    public List<AttendClassRecordVo> findAttendClassRecordDetailByClassLectureId(Long classLectureId) {
        List<AttendClassRecord> attendClassRecordList=this.findAttendClassRecordByClassLectureId(classLectureId);
        List<Long>  studentIds=BeanUtils.toList(attendClassRecordList,"studentId");
        studentIds=Utils.removeDuplicate(studentIds);
        List<Student> studentList=studentService.findByIds(studentIds,"studentId","phoneNo");
        Map<Long,Student> studentMap=BeanUtils.toMap(studentList,"studentId");
        List<AttendClassRecordVo> attendClassRecordVos=new ArrayList<>(attendClassRecordList==null?0:attendClassRecordList.size());
        if (attendClassRecordList!=null){
            for (AttendClassRecord attendClassRecord:attendClassRecordList){
                AttendClassRecordVo attendClassRecordVo=new AttendClassRecordVo();
                BeanUtils.copyProperties(attendClassRecordVo,attendClassRecord);
                Student student=studentMap.get(attendClassRecord.getStudentId());
                if (student!=null){
                    attendClassRecordVo.setStudentPhoneNo(student.getPhoneNo());
                }
                attendClassRecordVos.add(attendClassRecordVo);
            }
        }
        return attendClassRecordVos;
    }

    @Transactional
    @Override
    public void updateAttendClassRecord(Long classLectureId, List<AttendClassRecordUpdateVo> recordUpdateList,Integer attendanceRole) {
        //检查前一讲是否考勤了

        ClassLecture classLecture = findById(classLectureId);

        if( TimeUtils.now().before(DateUtils.addMinutes( classLecture.getClassDate() ,-15 ))){
            throw new BusException("上课时间前15分钟才开始考勤");
        }

        ClassLecture preAttendanceRecord = findAttendanceRecordByClassIdLectureNo(classLecture.getClassId(), classLecture.getLectureNo() - 1);




        if(preAttendanceRecord != null && preAttendanceRecord.getAttendanceStatus() != 1 ){
            throw new BusException("【第"+preAttendanceRecord.getLectureNo()+"讲】未考勤");
        }

        if(classLecture.getTeacherId() == null ){
            throw new BusException("【第"+classLecture.getLectureNo()+"讲】未排老师");
        }

        Map<Integer,Integer> count = new HashMap<>();

        for(AttendClassRecordUpdateVo d : recordUpdateList ){
            AttendClassRecord update = new AttendClassRecord();
            BeanUtils.copyProperties(update,d );
            update.setIsAttendance(1);
            //update.setFinanceFlag(0);
            update.setUpdateTime(TimeUtils.now());
            attendClassRecordService.updateSelectiveById(update);
            Integer num = count.get(update.getAttendanceStatus());
            if(num == null ){
                num = 0 ;
            }
            count.put(update.getAttendanceStatus(),num + 1 );
        }

        boolean b = courseClassService.updateCompletedLectureAmount(classLecture.getClassId(),classLecture.getLectureNo());

        if(b){
            finishLectureService.addFinishLecture(classLecture.getClassId(),classLecture.getLectureNo());
            JSONObject data = new JSONObject();
            data.put("classLectureId", classLecture.getClassLectureId() );
            producer.send("attendance",null , JSONS.toBytes(data));
        }

        ClassLecture update = new ClassLecture();
        update.setClassLectureId(classLectureId);
        update.setAttendanceStatus(1);
        update.setAttendanceTime(TimeUtils.now());
        update.setAttendanceAmount(count.get(0) == null ? Integer.valueOf(0) : count.get(0) );
        update.setAbsenceAmount(count.get(1) == null ? Integer.valueOf(0) : count.get(1) );
        update.setLateAmount(count.get(2) == null ? Integer.valueOf(0) : count.get(2) );
        update.setLeaveAmount(count.get(3) == null ? Integer.valueOf(0) : count.get(3) );
        update.setAttendanceRole(attendanceRole);
        update.setUpdateTime(TimeUtils.now());
        updateSelectiveById(update);

    }

    @Override
    @Transactional
    public void updateAttendClassAdvanceStatus( List<AttendClassRecordUpdateVo> attendClassRecordUpdateVoList) {
        if ( Utils.checkListEmpty(attendClassRecordUpdateVoList)){
            return;
        }
        for(AttendClassRecordUpdateVo d : attendClassRecordUpdateVoList ){
            AttendClassRecord update = new AttendClassRecord();
            BeanUtils.copyProperties(update,d );
            //update.setFinanceFlag(0);
            update.setUpdateTime(TimeUtils.now());
            attendClassRecordService.updateSelectiveById(update);
        }

    }

    public ClassLecture findAttendanceRecordByClassIdLectureNo(Long classId, Integer lectureNo) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("classId",classId).andEqualTo("lectureNo",lectureNo);
        return findOneByExample(example);

    }



    @Transactional
    @Override
    public void deleteAttendanceRecordForStudent(Long classId, Long regId, Integer startLectureNo, Integer endLectureNo) {
        List<ClassLecture> classLectureList = findClassLectureByClassId(classId);
        final List<Long> classLectureIds = new ArrayList<>(classLectureList.size());

        for(ClassLecture classLecture : classLectureList ){
            if( classLecture.getLectureNo().intValue() >= startLectureNo.intValue() && classLecture.getLectureNo().intValue() <= endLectureNo.intValue() ){
                classLectureIds.add(classLecture.getClassLectureId());
            }
        }

        deleteAttendanceRecordForStudent(regId,classLectureIds);
    }

    @Override
    public ClassLecture findAttendingClassLecture(Long teacherId) {
        //将要考勤
        Date now = TimeUtils.now();

        Example<ClassLecture> example = ClassLecture.createExample();
        Example.Criteria criteria = example.createCriteria();
        example.orderBy("startTime").asc();
        criteria.andEqualTo("attendanceStatus",0).andEqualTo("teacherId",teacherId ).andEqualTo("classDate",Utils.formatDate(TimeUtils.now(),"yyyy-MM-dd") );

        criteria.andGreaterThanOrEqualTo("startTime" , Utils.formatDate(DateUtils.addMinutes(now,-10),"HH:mm"));

        ClassLecture classLecture = findOneByExample(example);

        if(classLecture == null ){
            return null ;
        }

        CourseClass courseClass = courseClassService.findById(classLecture.getClassId());

        if(courseClass.getStatus() != 1 ){
            return null ;
        }

        return classLecture ;
    }

    @Override
    public List<ClassLecture> findClassLectureByTeacherIdClassDate(Long teacherId, Date date) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.orderBy("startTime");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("teacherId",teacherId );
        criteria.andEqualTo("classDate",date );
        return findListByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureByTeacherIdTime(Long teacherId, Date classTime, Integer timeOrientation, int limit) {
        Example<ClassLecture> example = ClassLecture.createExample();

        example.limit(limit);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("teacherId",teacherId);
        if(timeOrientation == 0 ){//下
            example.orderBy("classTime");
            criteria.andGreaterThan("classTime" ,classTime  );
            return findListByExample(example);
        }else{
            example.orderBy("classTime").desc();
            criteria.andLessThan("classTime" ,classTime  );
            List<ClassLecture> list = findListByExample(example);
            Collections.reverse(list);
            return list ;
        }

    }

    @Override
    public void clearTeacher(Long classId) {
        autoMapper.clearTeacher(classId);
    }

    @Override
    public void clearClassTime(Long classId) {
        autoMapper.clearClassTime(classId);
    }

    @Override
    public List<ClassLecture> findHahAttendanceClassLectureByClassId(Long classId) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.orderBy("lectureNo");
        example.createCriteria().andEqualTo("classId",classId).andEqualTo("attendanceStatus" ,1 );
        return findListByExample(example) ;
    }

    @Transactional
    @Override
    public void updateClassLecture(Long classId, Integer lectureAmount) {
        if(classId == null ){
            throw new NullPointerException();
        }
        CourseClass courseClass = courseClassService.findById(classId);
        if(courseClass.getRegAmount() > 0 ){
            throw new BusException("已有学生报名，不能调整讲次");
        }
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("classId" , classId );
        deleteByExample(example);
        createClassLecture(classId, lectureAmount);
    }


    @Transactional
    @Override
    public void rearrangeTeacherForLecture(Long classLectureId, Long teacherId, boolean updateAfterLecture,String remark) {

        ClassLecture classLecture = findById(classLectureId);
        if (!classLecture.getTeacherId().equals(teacherId)){
            ArrangeTeacherHistory arrangeTeacherHistory=new ArrangeTeacherHistory();
            arrangeTeacherHistory.setClassLectureId(classLectureId);
            arrangeTeacherHistory.setNowTeacherId(teacherId);
            arrangeTeacherHistory.setOrginTeacherId(classLecture.getTeacherId());
            arrangeTeacherHistory.setUpdateTime(TimeUtils.now());
            arrangeTeacherHistory.setCreateTime(TimeUtils.now());
            arrangeTeacherHistory.setRemark(remark);
            Principals.Principal principal=Principals.get();
            if (principal==null){
                throw new BusException("未查询到操作人，请登陆后操作");
            }
            arrangeTeacherHistory.setOperatorId(principal.id);
            arrangeTeacherHistory.setOperatorName(principal.name);
            arrangeTeacherHistoryService.insert(arrangeTeacherHistory);
        }

        if(classLecture.getClassTime() == null ){
            throw new BusException("班级未排时间");
        }

        if(Objects.equals(teacherId,classLecture.getTeacherId())){
            return ;
        }

        detectConflict(teacherId,classLecture.getClassDate(),classLecture.getStartTime(),classLecture.getEndTime() );

        classLecture.setTeacherId(teacherId);
        Teacher teacher = teacherService.findById(teacherId);
        classLecture.setTeacherName(teacher.getTeacherName());
        classLecture.setUpdateTime(TimeUtils.now());
        updateSelectiveById(classLecture);
    }

    @Override
    @Transactional
    public void reArrangeTeacherForLectrues(List<ClassLecture> classLectures, Long teacherId, String remark) {
        Teacher teacher = teacherService.findById(teacherId);

        Principals.Principal principal=Principals.get();
        if (principal==null){
            throw new BusException("未查询到操作人，请登陆后操作");
        }
        List<ArrangeTeacherHistory> arrangeLectureHistories = new ArrayList<>(10);
        for (ClassLecture classLecture : classLectures){
            if (!classLecture.getTeacherId().equals(teacherId)){
                ArrangeTeacherHistory arrangeTeacherHistory=new ArrangeTeacherHistory();
                arrangeTeacherHistory.setClassLectureId(classLecture.getClassLectureId());
                arrangeTeacherHistory.setNowTeacherId(teacherId);
                arrangeTeacherHistory.setOrginTeacherId(classLecture.getTeacherId());
                arrangeTeacherHistory.setUpdateTime(TimeUtils.now());
                arrangeTeacherHistory.setCreateTime(TimeUtils.now());
                arrangeTeacherHistory.setRemark(remark);
                arrangeTeacherHistory.setOperatorId(principal.id);
                arrangeTeacherHistory.setOperatorName(principal.name);
                arrangeLectureHistories.add(arrangeTeacherHistory);

                if(classLecture.getClassTime() == null ){
                    throw new BusException("班级未排时间");
                }

                detectConflict(teacherId,classLecture.getClassDate(),classLecture.getStartTime(),classLecture.getEndTime() );

                classLecture.setTeacherId(teacherId);
                classLecture.setTeacherName(teacher.getTeacherName());
                classLecture.setUpdateTime(TimeUtils.now());
                updateSelectiveById(classLecture);
            }
        }
        if (arrangeLectureHistories.size() != 0){
            arrangeTeacherHistoryService.insertBatch(arrangeLectureHistories);
        }
    }

    @Transactional
    @Override
    public void rearrangeTimeForLecture(Long classLectureId, String date, String time, boolean updateAfterLecture) {
        List<ArrangeLectureHistory> arrangeLectureHistoryList=new ArrayList<>();
        ClassLecture classLecture = findById(classLectureId);

        if(classLecture.getClassTime() == null ){
            throw new BusException("班级未排时间");
        }
        Principals.Principal principal= Principals.get();

        ArrangeLectureHistory arrangeLectureHistory=new ArrangeLectureHistory();
        arrangeLectureHistory.setCreateTime(TimeUtils.now());
        arrangeLectureHistory.setUpdateTime(TimeUtils.now());
        arrangeLectureHistory.setClassLectureId(classLectureId);
        arrangeLectureHistory.setOperatorId(principal.id);
        arrangeLectureHistory.setOperatorName(principal.name);
        arrangeLectureHistory.setOriginClassDate(classLecture.getClassDate());
        arrangeLectureHistory.setOriginStartTime(classLecture.getStartTime());
        arrangeLectureHistory.setOriginEndTime(classLecture.getEndTime());
        arrangeLectureHistoryList.add(arrangeLectureHistory);

        Date newDate = TimeUtils.parse(date ,"yyyy-MM-dd");
        Date oldDate = classLecture.getClassDate() ;

        classLecture.setClassDate(newDate);
        String[] times = time.split("-");
        classLecture.setStartTime(times[0]);
        classLecture.setEndTime(times[1]);
        classLecture.setClassTime(TimeUtils.parse(date + times[0] , "yyyy-MM-ddHH:mm"));
        classLecture.setUpdateTime(TimeUtils.now());
        updateSelectiveById(classLecture);



        if(updateAfterLecture){
            int offsetDay = (int)( ( newDate.getTime() - oldDate.getTime() ) / ( 24* 60 * 60 * 1000 ));
            List<ClassLecture> classLectureList = findClassLectureByClassId(classLecture.getClassId());
            for(int i = 0 ; i < classLectureList.size() ;i++ ){
                ClassLecture cl = classLectureList.get(i);
                if(cl.getLectureNo() > classLecture.getLectureNo() && i > 0 ){
                    ArrangeLectureHistory insert=new ArrangeLectureHistory();
                    insert.setCreateTime(TimeUtils.now());
                    insert.setUpdateTime(TimeUtils.now());
                    insert.setClassLectureId(cl.getClassLectureId());
                    insert.setOperatorId(principal.id);
                    insert.setOperatorName(principal.name);
                    insert.setOriginClassDate(cl.getClassDate());
                    insert.setOriginStartTime(cl.getStartTime());
                    insert.setOriginEndTime(cl.getEndTime());
                    arrangeLectureHistoryList.add(insert);


                    cl.setClassDate(DateUtils.addDays(classLectureList.get(i).getClassDate(), offsetDay));
                    cl.setStartTime(classLecture.getStartTime());
                    cl.setEndTime(classLecture.getEndTime());
                    cl.setClassTime(TimeUtils.parse(Utils.formatDate(cl.getClassDate(),"yyyy-MM-dd") + cl.getStartTime() , "yyyy-MM-ddHH:mm"));
                    cl.setUpdateTime(TimeUtils.now());
                    updateSelectiveById(cl);




                }
            }
        }
        if (arrangeLectureHistoryList.size()>0){
            arrangeLectureHistoryService.insertBatch(arrangeLectureHistoryList);
        }
    }

    @Override
    public void updateTime(Long classId, String time) {

        String[] times = time.split("-");
        ClassLecture update = new ClassLecture();
        update.setStartTime(times[0]);
        update.setEndTime(times[1]);

        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("classId",classId );

        updateSelectiveByExample(update,example );
    }

    @Override
    public void updateTeacher(Long classId, Long teacherId) {
        Teacher teacher = teacherService.findById(teacherId);
        ClassLecture update = new ClassLecture();
        update.setTeacherId(teacherId);
        update.setTeacherName(teacher.getTeacherName());

        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andEqualTo("classId",classId );

        updateSelectiveByExample(update,example );
    }

    @Override
    public List<ClassLecture> findByClassIdAndTime(List<Long> classIdList, Date startDate, Date endDate,Integer attendanceStatus,String ...columns) {
        if (classIdList==null ||classIdList.size()<=0){
            return  Collections.EMPTY_LIST;
        }
        Example<ClassLecture> example = ClassLecture.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("classId", classIdList);
        if (startDate!=null){
            criteria.andGreaterThanOrEqualTo("classDate",startDate);
        }
        if (endDate!=null){
            criteria.andLessThanOrEqualTo("classDate",endDate);
        }

        example.selectProperties(columns);
        if (attendanceStatus!=null){
            criteria.andEqualTo("attendanceStatus",attendanceStatus);
        }
        return this.findListByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureByClassIds(List<Long> classIds) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andIn("classId" , Utils.unique(classIds));
        example.orderBy("classDate");
        return findListByExample(example);
    }

    @Override
    public List<ClassLecture> findByIdsOrderByNo(List<Long> classLectureIds) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.createCriteria().andIn("classLectureId" , Utils.unique(classLectureIds));
        example.orderBy("lectureNo");
        return findListByExample(example);
    }

    @Override
    public List<ClassLecture> findRegClassLectureByRegId(StudentReg studentReg) {


        List<ClassLecture> classLectureList = findClassLectureByClassId(studentReg.getClassId());

        //不能根据classId,因为一个学生有可能报名同一课程多次
        List<ClassLecture> regClassLectureList = new ArrayList<>(classLectureList.size());
        for(ClassLecture classLecture : classLectureList ){
            if(classLecture.getLectureNo() >= studentReg.getStartAmount() && classLecture.getLectureNo() <=  studentReg.getEndAmount() ){
                regClassLectureList.add(classLecture);
            }
        }
        return regClassLectureList;
    }

    @Override
    public Map<Long, List<ClassLecture>> findRegClassLectureByRegs(List<StudentReg> studentRegs) {
        List<Long> classIds = Utils.unique(BeanUtils.toList(studentRegs, "classId"));
        Map<Long,List<ClassLecture>> map=new HashMap<>(studentRegs.size());

        List<ClassLecture> classLectureList=findClassLectureByClassIds(classIds);
        Map<Long, List<ClassLecture>> classLectureMap = BeanUtils.toGroup(classLectureList, "classId");


        for (StudentReg studentReg: studentRegs){
            List<ClassLecture> classLectures=classLectureMap.get(studentReg.getClassId());
            List<ClassLecture> realClassLectures=map.get(studentReg.getRegId());
            if (realClassLectures==null){
                realClassLectures=new ArrayList<>();
                map.put(studentReg.getRegId(),realClassLectures);
            }
            for(ClassLecture classLecture : classLectures ){
                if(classLecture.getLectureNo() >= studentReg.getStartAmount() && classLecture.getLectureNo() <=  studentReg.getEndAmount() ){
                    realClassLectures.add(classLecture);
                }
            }
        }


        return map;
    }

    @Override
    public void deleteAttendanceRecordForStudent(Long regId, final  List<Long> classLectureIds) {
        if(regId == null || classLectureIds == null ){
            throw new NullPointerException();
        }
        List<AttendClassRecord> studentShiftAttendClassRecord = attendClassRecordService.findStudentShiftAttendClassRecord(regId, classLectureIds);
        List<Long> attendClassRecordIds = BeanUtils.toList(studentShiftAttendClassRecord, "attendClassRecordId");
        Threads.dispatch(new Runnable() {
            @Override
            public void run() {
                attendClassRecordService.deleteShiftAttendClassRecord(attendClassRecordIds);
            }
        });
        try{
            Example<AttendClassRecord> example = AttendClassRecord.createExample();
            example.createCriteria().andEqualTo("regId",regId).andIn("classLectureId",classLectureIds);
            attendClassRecordService.deleteByExample(example);
        }catch (Exception e ){
            //
        }

        Threads.delay(new Runnable() {
            @Override
            public void run() {
                updateTotalAmount(classLectureIds);
            }
        },5);
    }

    @Override
    public List<Long> lectureNo2ClassLectureId(Long classId, List<Integer> lectureNos) {
        Example<ClassLecture> example = ClassLecture.createExample();
        example.selectProperties("lectureNo");
        example.orderBy("lectureNo");
        example.createCriteria().andEqualTo("classId",classId);
        List<ClassLecture> classLectureList = findListByExample(example);
        List<Long> classLectureIds = new ArrayList<>(classLectureList.size());
        for(ClassLecture classLecture : classLectureList ){
            for(Integer lectureNo : lectureNos ){
                if(lectureNo.equals(classLecture.getLectureNo())){
                    classLectureIds.add(classLecture.getClassLectureId());
                }
            }
        }
        return classLectureIds;
    }


    @Override
    public List<Long> lectureNo2ClassLectureId(Long classId, Integer startAmount, Integer endAmount) {
        List<Integer> list  = new ArrayList<>(endAmount -  startAmount +1 ) ;
        for(int i = startAmount ; i <= endAmount;i++ ){
            list.add(i);
        }
        return lectureNo2ClassLectureId(classId,list);
    }

    @Override
    public List<ClassLecture> findByClassIds(List<Long> classIds) {
        Example<ClassLecture> example=ClassLecture.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("classId",classIds);
        return this.findListByExample(example);
    }

    @Override
    public List<ClassLecture> findClassLectureBetweenDate(Date startDate, Date endDate,Integer attendanceStatus) {
        return autoMapper.findClassLectruesBetweenDate(startDate, endDate, attendanceStatus);
    }

    @Override
    public ClassLecture findLectureByClassIdLectureNo(long classId, Integer lectureNo) {
        Example<ClassLecture> example=ClassLecture.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("classId",classId).andEqualTo("lectureNo",lectureNo);
        return this.findOneByExample(example);
    }
}